#pragma once


#include "lsp.h"
#include <queue>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>

struct lsp_client
{
	int sockfd;						//Socket file descriptor
	int connid;						//Unique ID for connection
	int seqnum;						//Current message sequence number
	sockaddr_in server;				//Connection info for server
	hostent* hp;		
	std::queue<LSPMessage> read;	//Contains messages read from socket with payload
	std::queue<LSPMessage> to_send;	//Contains messages with payload to be sent
	pthread_mutex_t read_lock;		//Lock for read and read_lth
	pthread_mutex_t to_send_lock;	//Lock for to_send and to_send_lth
	pthread_mutex_t epoch_lock;
	pthread_cond_t new_msg_pushed;	//lsp thread signals main thread that message has been pushed to read
	LSPMessage last_sent;			//Holds last message sent so it can be sent again on the epoch
	pthread_t epoch_thread;
	pthread_t lsp_thread;				
	bool close_flag;				//Signals thread to finish
	int epochs_since_contact;		
	bool waiting_on_ack;
	bool connection_lost;
};

lsp_client* lsp_client_create(const char* dest, int port);
//The return value of this is what will be passed into the other functions as a_srv.
//Returns null if the create did not work


int lsp_client_read(lsp_client* a_client, uint8_t* pld);
//a_client is input. It will always be the same.
//pld is output. It will be a null terminated char*
//Returns length of pld if there was a message to read
//Returns 0 if there was no message to read
//Returns -1 if the connection was lost


bool lsp_client_write(lsp_client* a_client, uint8_t* pld, int lth);
//a_client is input. It will always be the same.
//pld is input. It should be a null terminated char*
//lth is input. It should be the length of pld including null character.
//Returns true if the write worked.
//Returns false if the connection was lost.


bool lsp_client_close(lsp_client* a_client);

void *lsp_client_lsp_thread(void *client);
void *lsp_client_epoch_thread(void *client);
void lsp_client_send_last(lsp_client* a_client);